﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="RepositoryTestsHelper.cs" company="">
//   
// </copyright>
// <summary>
//   Provides helper methods for consolidating duplicated code from test fixture base classes.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

#region

using System;
using System.Configuration;
using System.Data;
using System.Reflection;
using FluentNHibernate.Automapping;
using NHibernate;
using NHibernate.Tool.hbm2ddl;
using SharpArch.Core;
using SharpArch.Data.NHibernate;
using SharpArch.Data.NHibernate.FluentNHibernate;
using Configuration = NHibernate.Cfg.Configuration;

#endregion

namespace SharpArch.Testing.NHibernate
{
    /// <summary>
    /// Provides helper methods for consolidating duplicated code from test fixture base classes.
    /// </summary>
    public class RepositoryTestsHelper
    {
        private static Configuration cfg;
        private static ISessionFactory sessionFactory;

        /// <summary>
        /// Crée un shéma de base de données à partir du mapping NHibernate
        /// </summary>
        public static void InitializeDatabase()
        {
            InitializeNHibernateSession();
            IDbConnection connection = NHibernateSession.Current.Connection;
            new SchemaExport(cfg).Execute(false, true, false, connection, null);
        }

        /// <summary>
        /// Initialise NHibernate
        /// </summary>
        public static void InitializeNHibernateSession()
        {
            if (cfg != null)
            {
                NHibernateSession.Storage = new SimpleSessionStorage();
                NHibernateSession.SessionFactory = sessionFactory;
            }
            else
            {
                string[] mappingAssemblies = GetMappingAssemblies();
                string nhconfigfile = ConfigurationManager.AppSettings["nhibernate.configfile"];
                Check.Require(
                    !string.IsNullOrEmpty(nhconfigfile),
                    "please provide path to config file through nhibernate.configfile");

                AutoPersistenceModel autoPersistenceModel = GetAutoPersistenceModel(mappingAssemblies);
                cfg = NHibernateSession.Init(
                    new SimpleSessionStorage(),
                    mappingAssemblies,
                    autoPersistenceModel,
                    nhconfigfile);
                sessionFactory = NHibernateSession.SessionFactory;
            }
        }

        /// <summary>
        /// Liste des assembly contenant des mappings NHibernate (séparées par des ","), lu dans le fichier de configuration dans la clé nhibernate.mapping.assembly
        /// </summary>
        /// <returns>Liste des assemblies contenant des mappings NHibernate</returns>
        public static string[] GetMappingAssemblies()
        {
            string mappingAssembliesSetting = ConfigurationManager.AppSettings["nhibernate.mapping.assembly"];

            Check.Require(
                !string.IsNullOrEmpty(mappingAssembliesSetting),
                          "Please add an AppSetting to your app.config for 'nhibernate.mapping.assembly.' This setting " +
                          "takes a comma delimited list of assemblies containing NHibernate mapping files. Including '.dll' " +
                          "at the end of each is optional.");

            return mappingAssembliesSetting.Split(',');
        }

        /// <summary>
        /// Récupération des mappings
        /// </summary>
        /// <param name="assemblies">Liste des assemblies à parcourir</param>
        /// <returns>Model de persistence</returns>
        public static AutoPersistenceModel GetAutoPersistenceModel(string[] assemblies)
        {
            foreach (var asmName in assemblies)
            {
                Assembly asm = Assembly.Load(asmName);
                Type[] asmTypes = asm.GetTypes();

                foreach (Type asmType in asmTypes)
                {
                    if (typeof(IAutoPersistenceModelGenerator).IsAssignableFrom(asmType))
                    {
                        IAutoPersistenceModelGenerator generator =
                            Activator.CreateInstance(asmType) as IAutoPersistenceModelGenerator;
                        return generator.Generate();
                    }
                }
            }

            return null;
        }
    }
}